#include "main.h"
#include "def.h"
#include "sync.h"
#include "util.h"
#include "gui.h"
#include "net.h"

#include <maya/MGlobal.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnMesh.h>
#include <maya/MItDependencyNodes.h>
#include <maya/MSelectionList.h>
#include <maya/MEventMessage.h>
#include <maya/MCallbackIdArray.h>
#include <time.h>

#pragma message ("remove when VTRY/VCATCH refactored")
#include "..\Global\globaldef.h"

#pragma message ("todo reorganize 1")
#include "..\CommLib\PacketConven.h"

MObject			VSyncViewer::Selection::Transform	= MObject();
MObject			VSyncViewer::Selection::Mesh		= MObject();

void VSyncViewer::AddSamplerCallback(MObject material) {

	if(VUtil::IsTextureSupported(material)) {

		MStatus result;
		MNodeMessage::addAttributeChangedCallback(material, 
			VSyncViewer::CallbackWrappers::OnChangeSampler, 0, &result);
		
		if(MAYA_FAIL(result))
			return;
	}
}

bool VSyncViewer::Selection::IsValid() {

	return (Transform.hasFn(MFn::kTransform) && Mesh.hasFn(MFn::kMesh));
}

void VSyncViewer::Selection::Release() {
		
	Transform	= MObject();
	Mesh		= MObject();
}

bool VSyncViewer::Selection::InitMaterials() {
 
	MString channel[3] = {

		MString("liveview_color"),
		MString("liveview_normal"),
		MString("liveview_specular")
	};

	for(uint i = 0; i < 3; i++) {

		MPlug attribute;
		VUtil::GetObjectAttribute(Mesh, channel[i], attribute);
		
		MString channelString;
		MAYA_CONTINUE_IF_FAIL(attribute.getValue(channelString));

		MStringArray channelArray;
		MAYA_CONTINUE_IF_FAIL(channelString.split(';', channelArray));

		for(uint j = 0; j < channelArray.length(); j++) {
		
			MString channelPartString = channelArray[j];
			MStringArray channelPartArray;
			MAYA_CONTINUE_IF_FAIL(channelPartString.split(',', channelPartArray));

			for(uint k = 0; k < channelPartArray.length(); k++) {

				MString partMaterialString = channelPartArray[k];
				MObject partMaterialObject;
				if(VUtil::GetSurfaceTextureByName(partMaterialString, partMaterialObject)) {

					MStatus result;
					MCallbackId materialCallback = MNodeMessage::addAttributeChangedCallback(partMaterialObject, 
						VSyncViewer::CallbackWrappers::OnChangeSampler, 0, &result);
					
					MAYA_CONTINUE_IF_FAIL(result);
				}
			}
		}
	}

	return true;
}

bool VSyncViewer::Selection::InitAttributes() {

	MString meshName;
	if(!VUtil::GetObjectName(Mesh, meshName))
		return false;

	MString command = "InitalizeObjectAttributes(\"" + meshName + "\");";
	MAYA_RETURN_IF_FAIL(MGlobal::executeCommand(command, false, false), false);
	return true;
}

bool VSyncViewer::Selection::InitCallbacks() {
	
	MCallbackIdArray callbacks;
	
	if(MAYA_FAIL(MNodeMessage::nodeCallbacks(Mesh, callbacks)))
		return false;

	if(callbacks.length() == 0) {

		MStatus result;
		MNodeMessage::addAttributeChangedCallback(Mesh, VSyncViewer::CallbackWrappers::OnChangeGeometry, 0, &result);
		MAYA_RETURN_IF_FAIL(result, false);

		MNodeMessage::addNodePreRemovalCallback ( Mesh, VSyncViewer::CallbackWrappers::SceneRemoveObject, 0, &result);
		MAYA_RETURN_IF_FAIL(result, false);
	
		callbacks.clear();
	}

	if(MAYA_FAIL(MNodeMessage::nodeCallbacks(Transform, callbacks)))
		return false;

	if(callbacks.length() == 0) {

		MStatus result;
		MNodeMessage::addAttributeChangedCallback(Transform, VSyncViewer::CallbackWrappers::OnChangeTransform, 0, &result);
		MAYA_RETURN_IF_FAIL(result, false);


		MNodeMessage::addNodePreRemovalCallback ( Transform, VSyncViewer::CallbackWrappers::SceneRemoveObject, 0, &result);
		MAYA_RETURN_IF_FAIL(result, false);
	
		callbacks.clear();
	}

	return true;
}